home *** CD-ROM | disk | FTP | other *** search
Wrap
SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) NNNNAAAAMMMMEEEE ssssrrrraaaannnndddd66664444, ddddrrrraaaannnndddd66664444, ddddrrrraaaannnndddd66664444____aaaaddddvvvvaaaannnncccceeee, ddddrrrraaaannnndddd66664444____ggggeeeetttt, ddddrrrraaaannnndddd66664444____ggggeeeettttvvvv, ddddrrrraaaannnndddd66664444____mmmmaaaaxxxxtttthhhhrrrreeeeaaaaddddssss, ddddrrrraaaannnndddd66664444____sssseeeetttt, ddddrrrraaaannnndddd66664444____sssseeeettttvvvv, ddddrrrraaaannnndddd66664444____tttthhhhrrrreeeeaaaadddd - Thread- safe parallel 64-bit random number generator SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS Fortran synopsis: RRRREEEEAAAALLLL FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNN SSSSRRRRAAAANNNNDDDD66664444 ((((_h_a_r_v_e_s_t)))) RRRREEEEAAAALLLL _h_a_r_v_e_s_t DDDDOOOOUUUUBBBBLLLLEEEE PPPPRRRREEEECCCCIIIISSSSIIIIOOOONNNN FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNN DDDDRRRRAAAANNNNDDDD66664444 ((((_h_a_r_v_e_s_t)))) DDDDOOOOUUUUBBBBLLLLEEEE PPPPRRRREEEECCCCIIIISSSSIIIIOOOONNNN _h_a_r_v_e_s_t SSSSUUUUBBBBRRRROOOOUUUUTTTTIIIINNNNEEEE DDDDRRRRAAAANNNNDDDD66664444____AAAADDDDVVVVAAAANNNNCCCCEEEE ((((_c_o_u_n_t)))) IIIINNNNTTTTEEEEGGGGEEEERRRR****8888 _c_o_u_n_t SSSSUUUUBBBBRRRROOOOUUUUTTTTIIIINNNNEEEE DDDDRRRRAAAANNNNDDDD66664444____GGGGEEEETTTT ((((_s_e_e_d,,,, _c_o_u_n_t,,,, _t_h_r_e_a_d)))) IIIINNNNTTTTEEEEGGGGEEEERRRR****8888 _s_e_e_d,,,, _c_o_u_n_t IIIINNNNTTTTEEEEGGGGEEEERRRR _t_h_r_e_a_d SSSSUUUUBBBBRRRROOOOUUUUTTTTIIIINNNNEEEE DDDDRRRRAAAANNNNDDDD66664444____GGGGEEEETTTTVVVV ((((_s_t_a_t_e,,,, _c_o_u_n_t)))) IIIINNNNTTTTEEEEGGGGEEEERRRR****8888 _s_t_a_t_e(*),,,, _c_o_u_n_t(*) IIIINNNNTTTTEEEEGGGGEEEERRRR FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNN DDDDRRRRAAAANNNNDDDD66664444____MMMMAAAAXXXXTTTTHHHHRRRREEEEAAAADDDDSSSS (((()))) SSSSUUUUBBBBRRRROOOOUUUUTTTTIIIINNNNEEEE DDDDRRRRAAAANNNNDDDD66664444____SSSSEEEETTTT ((((_s_e_e_d)))) IIIINNNNTTTTEEEEGGGGEEEERRRR****8888 _s_e_e_d SSSSUUUUBBBBRRRROOOOUUUUTTTTIIIINNNNEEEE DDDDRRRRAAAANNNNDDDD66664444____SSSSEEEETTTTVVVV ((((_s_t_a_t_e,,,, _c_o_u_n_t)))) IIIINNNNTTTTEEEEGGGGEEEERRRR****8888 _s_t_a_t_e(*),,,, _c_o_u_n_t(*) IIIINNNNTTTTEEEEGGGGEEEERRRR FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNN DDDDRRRRAAAANNNNDDDD66664444____TTTTHHHHRRRREEEEAAAADDDD ((((_t_h_r_e_a_d)))) IIIINNNNTTTTEEEEGGGGEEEERRRR _t_h_r_e_a_d C/C++ synopsis: ####iiiinnnncccclllluuuuddddeeee <<<<ssssccccssssllll....hhhh>>>> ffffllllooooaaaatttt ssssrrrraaaannnndddd66664444 ((((ffffllllooooaaaatttt *_h_a_r_v_e_s_t))));;;; ddddoooouuuubbbblllleeee ddddrrrraaaannnndddd66664444 ((((ddddoooouuuubbbblllleeee *_h_a_r_v_e_s_t))));;;; vvvvooooiiiidddd ddddrrrraaaannnndddd66664444____aaaaddddvvvvaaaannnncccceeee ((((lllloooonnnngggg lllloooonnnngggg _c_o_u_n_t))));;;; vvvvooooiiiidddd ddddrrrraaaannnndddd66664444____ggggeeeetttt ((((lllloooonnnngggg lllloooonnnngggg *_s_e_e_d, lllloooonnnngggg lllloooonnnngggg *_c_o_u_n_t, iiiinnnntttt _t_h_r_e_a_d))));;;; vvvvooooiiiidddd ddddrrrraaaannnndddd66664444____ggggeeeettttvvvv ((((lllloooonnnngggg lllloooonnnngggg _s_t_a_t_e[], lllloooonnnngggg lllloooonnnngggg _c_o_u_n_t[]))));;;; iiiinnnntttt ddddrrrraaaannnndddd66664444____mmmmaaaaxxxxtttthhhhrrrreeeeaaaaddddssss ((((vvvvooooiiiidddd))));;;; PPPPaaaaggggeeee 1111 SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) vvvvooooiiiidddd ddddrrrraaaannnndddd66664444____sssseeeetttt ((((lllloooonnnngggg lllloooonnnngggg _s_e_e_d))));;;; vvvvooooiiiidddd ddddrrrraaaannnndddd66664444____sssseeeettttvvvv ((((lllloooonnnngggg lllloooonnnngggg _s_t_a_t_e[], lllloooonnnngggg lllloooonnnngggg _c_o_u_n_t[]))));;;; iiiinnnntttt ddddrrrraaaannnndddd66664444____tttthhhhrrrreeeeaaaadddd ((((iiiinnnntttt _t_h_r_e_a_d))));;;; IIIIMMMMPPPPLLLLEEEEMMMMEEEENNNNTTTTAAAATTTTIIIIOOOONNNN These routines are part of the SCSL Scientific Library and can be loaded using either the ----llllssssccccssss or the ----llllssssccccssss____mmmmpppp option. The ----llllssssccccssss____mmmmpppp option directs the linker to use the multi-processor version of the library. When linking to SCSL with ----llllssssccccssss or ----llllssssccccssss____mmmmpppp, the default integer size is 4 bytes (32 bits). Another version of SCSL is available in which integers are 8 bytes (64 bits). This version allows the user access to larger memory sizes and helps when porting legacy Cray codes. It can be loaded by using the ----llllssssccccssss____iiii8888 option or the ----llllssssccccssss____iiii8888____mmmmpppp option. A program may use only one of the two versions; 4-byte integer and 8-byte integer library calls cannot be mixed. The C and C++ prototypes shown above are appropriate for the 4-byte integer version of SCSL. When using the 8-byte integer version, the variables of type iiiinnnntttt become lllloooonnnngggg lllloooonnnngggg and the <<<<ssssccccssssllll____iiii8888....hhhh>>>> header file should be included. DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN These routines comprise a 64-bit thread-safe parallel random number generator that is based on the linear congruent sequence Y(n+1) = (a X(n) + c) mod 2^64. The parameters a and c are chosen from Knuth, _T_h_e _A_r_t _o_f _C_o_m_p_u_t_e_r _P_r_o_g_r_a_m_m_i_n_g , Vol. 2, 3rd edition, pp. 106-108: a = 6364136223846793005 c = 1 Y(n+1) is then converted to a floating point value in the range [0,1). The thread safety is ensured by separating the RNG state for each thread. Thus, each thread generates an independent random sequence starting from predefined values. Up to ddddrrrraaaannnndddd66664444____mmmmaaaaxxxxtttthhhhrrrreeeeaaaaddddssss(((()))) parallel streams of random numbers can be supported simultaneously. ssssrrrraaaannnndddd66664444 This function returns a single precision random number in the range [0,1); the same value is returned in the argument, if provided. ddddrrrraaaannnndddd66664444 This function returns a double precision random number in the range [0,1); the same value is returned in the argument, if provided. ddddrrrraaaannnndddd66664444____aaaaddddvvvvaaaannnncccceeee PPPPaaaaggggeeee 2222 SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) This routine advances the internal state table entries for the calling thread as if ssssrrrraaaannnndddd66664444(((()))) or ddddrrrraaaannnndddd66664444(((()))) had been called _c_o_u_n_t times. ddddrrrraaaannnndddd66664444____ggggeeeetttt This routine obtains the starting point of ssssrrrraaaannnndddd66664444(((()))) and ddddrrrraaaannnndddd66664444(((()))), as well as the invocation count for the thread specified in the third argument. ddddrrrraaaannnndddd66664444____ggggeeeettttvvvv This routine provides the internal state of ssssrrrraaaannnndddd66664444(((()))) and ddddrrrraaaannnndddd66664444(((()))). The arguments are arrays of seeds and invocation counts that can be given as arguments to ddddrrrraaaannnndddd66664444____sssseeeettttvvvv(((()))). The array arguments must have at least ddddrrrraaaannnndddd66664444____mmmmaaaaxxxxtttthhhhrrrreeeeaaaaddddssss(((()))) elements. ddddrrrraaaannnndddd66664444____mmmmaaaaxxxxtttthhhhrrrreeeeaaaaddddssss This function returns the maximum number of random number streams that can be generated in parallel. The internal state tables used in ddddrrrraaaannnndddd66664444____ggggeeeettttvvvv(((()))) and ddddrrrraaaannnndddd66664444____sssseeeettttvvvv(((()))) have ddddrrrraaaannnndddd66664444____mmmmaaaaxxxxtttthhhhrrrreeeeaaaaddddssss(((()))) entries. ddddrrrraaaannnndddd66664444____sssseeeetttt This routine sets the starting point of ssssrrrraaaannnndddd66664444(((()))) and ddddrrrraaaannnndddd66664444(((()))). By default the generator is initialized to -1. ddddrrrraaaannnndddd66664444____sssseeeettttvvvv This routine sets the internal state of ssssrrrraaaannnndddd66664444(((()))) and ddddrrrraaaannnndddd66664444(((()))). The arguments are arrays of seeds and invocation counts, as returned by ddddrrrraaaannnndddd66664444____ggggeeeettttvvvv, for example. The array arguments must have ddddrrrraaaannnndddd66664444____mmmmaaaaxxxxtttthhhhrrrreeeeaaaaddddssss(((()))) elements. ddddrrrraaaannnndddd66664444____tttthhhhrrrreeeeaaaadddd After a call this routine, the next invocations of ssssrrrraaaannnndddd66664444(((()))) and ddddrrrraaaannnndddd66664444(((()))) will have the same effect as if called from the base thread number specified in the argument to ddddrrrraaaannnndddd66664444____tttthhhhrrrreeeeaaaadddd(((()))). This function returns the base thread number that had previously been generating the random sequence. EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS Below are several usage examples for RRRRAAAANNNNDDDD66664444 routines. Example 1: Initialize the internal RNG state table with a single seed value and generate a random number for each thread. Fortran 77: EXTERNAL SRAND64 REAL SRAND64 INTEGER*8 SEED REAL S1, DUMMY SEED = 1 PPPPaaaaggggeeee 3333 SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) CALL DRAND64_SET(SEED) C Each thread gets a different random number C$OMP PARALLEL PRIVATE(S1, DUMMY) S1 = SRAND64(DUMMY) C$OMP END PARALLEL C/C++: #include <scsl.h> float s1, dummy; long long seed = 1LL; drand64_set(seed); /* Each thread gets a different random number */ #pragma omp parallel private(s1, dummy) { s1 = srand64(&dummy); } Example 2: After saving the RNG state table, generate 11 random numbers for each thread. Then restore the state table and use ddddrrrraaaannnndddd66664444____aaaaddddvvvvaaaannnncccceeee(((()))) to "skip" 10 random numbers. The next random number generated for each thread should be identical to the 11th value from the original stream. Fortran 90: INTEGER(KIND=8), DIMENSION(:), ALLOCATABLE :: STATE, COUNT EXTERNAL DRAND64_MAXTHREADS, OMP_GET_THREAD_NUM, DRAND64 INTEGER :: I, TABLE_SIZE, DRAND64_MAXTHREADS, OMP_GET_THREAD_NUM REAL(KIND=8) :: D1, DUMMY, DRAND64 TABLE_SIZE = DRAND64_MAXTHREADS() ALLOCATE(STATE(TABLE_SIZE)) ALLOCATE(COUNT(TABLE_SIZE)) CALL DRAND64_GETV(STATE, COUNT) !$OMP PARALLEL PRIVATE(I, D1, DUMMY) DO I = 1, 11 D1 = DRAND64(DUMMY) END DO PRINT *, OMP_GET_THREAD_NUM(), D1 !$OMP END PARALLEL CALL DRAND64_SETV(STATE, COUNT) !$OMP PARALLEL PRIVATE(D1, DUMMY) DRAND64_ADVANCE(10_8) D1 = DRAND64(DUMMY) PRINT *, OMP_GET_THREAD_NUM(), D1 !$OMP END PARALLEL C/C++: #include <scsl.h> PPPPaaaaggggeeee 4444 SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) #include <omp.h> #include <stdlib.h> #include <stdio.h> long long *state, *count; int i, table_size; double d1, dummy; table_size = drand64_maxthreads(); state = (long long *) malloc(table_size * sizeof(long long)); count = (long long *) malloc(table_size * sizeof(long long)); drand64_getv(state, count); #pragma omp parallel private(i, d1, dummy) { for (i = 0; i < 11; i++) d1 = drand64(&dummy); printf("%d, %g0, omp_get_thread_num(), d1); } drand64_setv(state, count); #pragma omp parallel private(d1, dummy) { drand64_advance(10LL); d1 = drand64(&dummy); printf("%d, %g0, omp_get_thread_num(), d1); } Example 3: Using only a single thread, generate 10 independent streams of random numbers. Fortran 77: EXTERNAL DRAND64_THREAD, SRAND64 INTEGER DRAND64_THREAD REAL SRAND64 INTEGER I, J, OLDID REAL STREAM(1000,10), DUMMY DO J = 1, 10 OLDID = DRAND64_THREAD(J-1) DO I = 1, 1000 STREAM(I, J) = SRAND64(DUMMY) END DO END DO C RESTORE ORIGINAL BASE THREAD OLDID = DRAND64_THREAD(0) C/C++: #include <scsl.h> int i, j, oldid; float stream[10][1000], dummy; for (i = 0; i < 10; i++) { oldid = drand64_thread(i); PPPPaaaaggggeeee 5555 SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) SSSSRRRRAAAANNNNDDDD66664444((((3333SSSS)))) for (j = 0; j < 1000; j++) stream[i][j] = srand64(&dummy); } /* restore original base thread */ oldid = drand64_thread(0); CCCCAAAAUUUUTTTTIIIIOOOONNNNSSSS Care is required when using ddddrrrraaaannnndddd66664444____tttthhhhrrrreeeeaaaadddd(((()))) in parallel regions. If multiple parallel threads possess the same RRRRAAAANNNNDDDD66664444 base thread number as assigned with a call to ddddrrrraaaannnndddd66664444____tttthhhhrrrreeeeaaaadddd(((()))), then thread safety will be compromised, with different threads no longer producing independent random sequences. The statistical randomness of the resulting individual sequences will also likely be degraded. SSSSEEEEEEEE AAAALLLLSSSSOOOO IIIINNNNTTTTRRRROOOO____SSSSCCCCSSSSLLLL(3S), DDDDRRRRAAAANNNNDDDD44448888(3C) PPPPaaaaggggeeee 6666